package com.ocgs.service.impl;

import com.ocgs.base.core.exception.BaseDAOException;
import com.ocgs.base.core.exception.BaseServiceException;
import com.ocgs.base.util.DateUtil;
import com.ocgs.dao.impl.ProductDAOImpl;
import com.ocgs.dao.impl.StorageDAOImpl;
import com.ocgs.model.Product;
import com.ocgs.model.StorageRecord;
import com.ocgs.pagination.PaginatedListImpl;
import com.ocgs.pagination.page.PageContext;
import com.ocgs.service.StorageService;
import org.displaytag.pagination.PaginatedList;

import java.math.BigDecimal;
import java.util.List;

/**
 * Created with IntelliJ IDEA.
 * User: bryant
 * Date: 10/21/12
 * Time: 3:40 PM
 * To change this template use File | Settings | File Templates.
 */
public class StorageServiceImpl implements StorageService {

    private StorageDAOImpl storageDAO;
    private ProductDAOImpl productDAO;

    public ProductDAOImpl getProductDAO() {
        return productDAO;
    }

    public void setProductDAO(ProductDAOImpl productDAO) {
        this.productDAO = productDAO;
    }

    public int deleteByPrimaryKey(Integer id) throws BaseServiceException {
       try{
           return storageDAO.deleteByPrimaryKey(id);
       }catch (BaseDAOException e){
           throw new BaseServiceException(e);
       }

    }

    public StorageRecord storagePutIn(StorageRecord record) throws BaseServiceException{
        try{
            record.setOnCreated(DateUtil.getCurrentTimestamp());
            record.setType("I");
            storageDAO.insert(record);
            Product p = new Product();
            p = productDAO.selectByPrimaryKey(record.getProductId());
            p.setStorage(calculateStorage(p,record,"A"));
            p.setCostPrice(calculateCostPrice(p,record));
            p.setPurchasePrice(record.getPurchasePrice());
            p.setLastUpdateTime(DateUtil.getCurrentTimestamp());
            productDAO.updateByPrimaryKey(p);
            return record;
        }catch (BaseDAOException e){
            throw new BaseServiceException(e);
        }
    }
    public int insertSelective(StorageRecord record) throws BaseServiceException {
        try{
            return storageDAO.insert(record);
        }catch (BaseDAOException e){
            throw new BaseServiceException(e);
        }
    }

    
    public StorageRecord selectByPrimaryKey(Integer id) throws BaseServiceException {
        try{
            return storageDAO.selectByPrimaryKey(id);
        }catch (BaseDAOException e){
            throw new BaseServiceException(e);
        }
    }

    
    public int updateByPrimaryKeySelective(StorageRecord record) throws BaseServiceException {
        try{
            return storageDAO.updateByPrimaryKeySelective(record);
        }catch (BaseDAOException e){
            throw new BaseServiceException(e);
        }
    }

    @Override
    public int updateByPrimaryKeyWithBLOBs(StorageRecord record) throws BaseServiceException {
        return 0;  //To change body of implemented methods use File | Settings | File Templates.
    }


    public int updateByPrimaryKey(StorageRecord record) throws BaseServiceException {
        try{
            return storageDAO.updateByPrimaryKey(record);
        }catch (BaseDAOException e){
            throw new BaseServiceException(e);
        }
    }

    public void setStorageDAO(StorageDAOImpl storageDAO) throws BaseServiceException {
        this.storageDAO = storageDAO;
    }

    public StorageDAOImpl getStorageDAO() throws BaseServiceException {
        return storageDAO;
    }

    public PaginatedList findAllInOutStorageForPagination(PaginatedListImpl paginatedList,Product product) throws BaseServiceException{

        try{
            PageContext page = PageContext.getPageContext();
            List<StorageRecord> storages = storageDAO.findAllInOutStorage(product);
            if(storages==null||storages.size()==0)
                return null;
            paginatedList.setList(storages);
            paginatedList.setTotalNumberOfRows(page.getTotalRows());
            return  paginatedList;
        }catch (BaseDAOException e){
            throw new BaseServiceException(e);
        }
    }

    public StorageRecord storageRemoval(StorageRecord record) throws BaseServiceException{
        try{
            record.setOnCreated(DateUtil.getCurrentTimestamp());
            record.setType("O");
            Product p = new Product();
            p = productDAO.selectByPrimaryKey(record.getProductId());
            BigDecimal storage = calculateStorage(p,record,"R");
            if(storage.intValue()<0)
                throw new BaseServiceException("error.no.more.storage");
            storageDAO.insert(record);
            p.setStorage(storage);
            p.setLastUpdateTime(DateUtil.getCurrentTimestamp());
            productDAO.updateByPrimaryKey(p);
            return record;
        }catch (BaseDAOException e){
            throw new BaseServiceException(e);
        }
    }

    private BigDecimal calculateCostPrice(Product p,StorageRecord s){
        BigDecimal currentPrice = p.getCostPrice()==null?new BigDecimal(0):p.getCostPrice();
        BigDecimal currentStorage = p.getStorage()==null?new BigDecimal(0):p.getStorage();
        BigDecimal newPrice = s.getPurchasePrice()==null?new BigDecimal(0):s.getPurchasePrice();
        BigDecimal newStorage = s.getAmount()==null?new BigDecimal(0):s.getAmount();
        BigDecimal totalPrice =  (currentStorage.multiply(currentPrice)).add(newStorage.multiply(newPrice));
        BigDecimal totalAmount = currentStorage.add(newStorage);
        if(totalAmount.intValue()!=0)
            return totalPrice.divide(totalAmount,2,BigDecimal.ROUND_HALF_DOWN);
        else return new BigDecimal(0);
    }

    private BigDecimal calculateStorage(Product p,StorageRecord s,String operate){
        BigDecimal oriStorage = p.getStorage()==null?new BigDecimal(0):p.getStorage();
        BigDecimal newStorage = s.getAmount()==null?new BigDecimal(0):s.getAmount();
        if("A".equalsIgnoreCase(operate))
            return oriStorage.add(newStorage);
        else return oriStorage.subtract(newStorage);
    }
}
